#ifndef SEMANTICO_H_
#define SEMANTICO_H_

#include <iostream>
#include <list>
#include <vector>

#include "Hash.h"
#include "Arvore.h"

#include "IdentificadorProcFunc.h"
#include "IdentificadorVariavel.h"
#include "IdentificadorParametro.h"

struct TokenExpressao
{
    std::string token;
    std::string categoria; // "procedimento" "funcao" "variavel" "numero" "simbolo" "booleano"
    std::string tipo;      // "i" integer  "b" boolean
    int         n;         // numero de parametros
    std::vector<IdentificadorParametro *> parametros;
};

class Semantico
{
    public:

    	Semantico();

    	~Semantico();

        bool analisar(Arvore *pArvore, Hash *pHash, NoArvore *pNoErros);

        // verifica se alguma funcao foi declarada mais de uma vez no mesmo escopo
        bool validarDeclaracaoFuncao(NoArvore *pNoAtual);
        bool percorrerFuncoes(NoArvore *pNoComando);

        // verifica se alguma variavel foi declarada mais de uma vez no mesmo escopo
        bool validarDeclaracaoVariavel(NoArvore *pNoAtual);
        bool percorrerVariaveis(NoArvore *pNoVariavel);

        // verifica se todas as variaveis de um bloco foram declaradas
        bool validarVariaveisUsadas(NoArvore *pNoAtual);
        bool percorrerComandos(NoArvore *pNoComando);
        
        // verifica se pIdentificador foi declarado
        bool variavelDeclarada(NoArvore *pNoComando, std::string pIdentificador);
        
        bool validarExpressao(std::list<std::string> *pExpressao, NoArvore *pNoPai, std::string &pRetorno);
        std::string buscarProcedimento(std::string pIdentificador, NoArvore *pNoPai);
        void removerParenteses(std::vector<TokenExpressao> &tokens);
        bool fazerOperacoes(std::vector<TokenExpressao> &tokens);
        bool callFuncao(std::vector<TokenExpressao> &tokens);
        void resolverComparacoes(std::vector<TokenExpressao> &tokens);
        void resolverOrAnd(std::vector<TokenExpressao> &tokens);
        
        bool isNumero(std::string pIdentificador);
        bool isSimbolo(std::string pIdentificador);
        bool isBooleano(std::string pIdentificador);

    private:

        NoArvore *mNoErro;
		Hash     *mTabelaHash;
		Arvore   *mArvore;
};

#endif /*SEMANTICO_H_*/
